
# RTP（Real-time Transport Protocol）实时传输协议

# aiortc: 基于 Python 的异步 WebRTC 库

# aiortc中的核心WebRTC组件遵循标准WebRTC架构：
# RTCPeerConnection：管理整个 WebRTC 会话的中央控制器
# RTCRtpTransceiver：将发送方和接收方配对，实现双向媒体流
# RTCRtpSender：处理传出的媒体轨道数据
# RTCRtpReceiver：处理传入的媒体轨道数据
# RTCDataChannel：支持点对点应用程序数据交换
# 传输层组件：提供安全、可靠的通信




# SDP 协商（信令层）：作用​​：通过交换 SDP（Session Description Protocol）描述媒体参数和网络信息，完成媒体协商
# 关键流程​​：
# ​​Offer/Answer 模型​​：
# ​​Offer​​：发起方（Caller）生成包含自身支持的编解码器（如 VP8、H264）、SSRC、传输协议（RTP/RTCP）等信息的 SDP Offer。
# ​​Answer​​：接收方（Callee）回复 SDP Answer，确认双方支持的媒体格式和参数。
# 示例：a=rtpmap:111 opus/48000/2 表示协商 Opus 音频编解码。
# ​​ICE Candidates 交换​​：
# SDP 中嵌入 ICE Candidate（如 a=candidate:1 udp 2122260223 192.168.1.100 54321 typ host），描述本地/公网 IP、端口、协议（UDP/TCP）等。
# ​​Bundle 与 RTCP-MUX​​：
# 通过 a=group:BUNDLE 合并多个媒体流到单一传输通道，减少端口占用。
# ​​安全相关​​：SDP 本身不加密，需通过信令服务器（如 WebSocket over HTTPS）安全传输。



# ICE 传输（网络穿透）：通过 ICE（Interactive Connectivity Establishment）穿透 NAT/防火墙，建立最优传输路径
# "候选人"(Candidate)是指网络连接的可能端点，用于在两个对等体之间建立直接连接。
# 核心组件​​：
# ​​Candidate 收集​​：
    # ​​Host Candidate​​：本地 IP 和端口。
    # ​​Server-Reflexive Candidate​​：通过 STUN 服务器获取的公网映射（如 a=candidate:... typ srflx）。
    # ​​Relay Candidate​​：通过 TURN 服务器中继（如 a=candidate:... typ relay），用于极端 NAT 场景。
# ​​优先级排序​​：
# 按 Candidate 类型（host > srflx > relay）和网络距离排序，优先选择低延迟路径。
# ​​连通性检查​​：
# 通过 STUN Binding Request/Response 测试 Candidate 对的可达性，成功后建立 PeerConnection。
# ​​穿透策略​​：
# 直接 P2P 连接（最优），失败时降级使用 TURN 中继。




# DTLS-SRTP 加密（媒体安全）：通过 DTLS 握手协商密钥，派生 SRTP 密钥对媒体流加密，防止窃听和篡改。




# ​​信令阶段​​：SDP 交换媒体参数和 ICE Candidate。
# ​​传输建立​​：ICE 完成穿透，选择最佳 Candidate 对。
# ​​安全通道​​：DTLS 握手后，SRTP 加密媒体流。
# ​​媒体传输​​：加密的 RTP/RTCP 通过 ICE 建立的通道传输。



# RTCPeerConnection 类
# 这是 AIORTC 的核心类，代表一个 WebRTC 连接端点。主要功能包括：
#     创建和管理本地/远程 SDP 描述
#     处理 ICE 候选收集和交换
#     管理媒体和数据通道

from aiortc import RTCPeerConnection

pc = RTCPeerConnection()


# 媒体流处理
# 从摄像头/麦克风捕获、播放媒体文件、生成测试图案、自定义媒体处理流水线
from aiortc.contrib.media import MediaPlayer, MediaRecorder

# 从设备捕获
player = MediaPlayer('/dev/video0', format='v4l2')
# 播放文件
player = MediaPlayer('input.mp4')
# 录制到文件
recorder = MediaRecorder('output.mp4')


# 数据通道： 支持通过 DataChannel 进行任意数据的双向通信：
# 创建数据通道
channel = pc.createDataChannel('chat')

@channel.on("message")
def on_message(message):
    print("收到消息:", message)

# 发送消息
channel.send("Hello!")



# TURN 和 STUN  是两种用于解决 NAT (网络地址转换) 穿越问题的协议，广泛应用于实时通信系统如 VoIP、视频会议和 WebRTC 等技术中。

# STUN 是一种客户端-服务器协议，允许 NAT 后的设备发现其公共 IP 地址和端口映射信息

# 工作原理
# ​​客户端发送请求​​：位于 NAT 后的设备向公网 STUN 服务器发送请求
# ​​服务器响应​​：STUN 服务器返回客户端的公网 IP 和端口信息
# ​​信息交换​​：客户端使用这些信息与其他对等端建立直接连接

# STUN 消息类型
# Binding Request：客户端向服务器查询其公网地址
# Binding Response：服务器返回客户端的映射地址
# Binding Error Response：错误响应

# STUN 的局限性
# 无法解决对称型 NAT 的穿越问题
# 不提供中继功能，连接失败时无法建立通信

# 对称型NAT：每次访问都生成随机ip和端口



# TURN 是 STUN 的扩展，当直接点对点连接无法建立时，通过中继服务器转发数据。
# 工作原理
# ​​客户端分配请求​​：客户端向 TURN 服务器请求分配中继地址
# ​​服务器响应​​：服务器分配公网 IP 和端口作为中继点
# ​​数据中继​​：所有通信数据通过 TURN 服务器转发

# TURN 消息类型
# Allocate：请求分配中继地址
# Refresh：刷新分配
# Send/Data：通过中继发送/接收数据
# ChannelBind：建立通道绑定

# STUN​​：用于发现 NAT 映射后的公网地址
# ​​TURN​​：当直接连接失败时提供中继服务

# 实际应用中的组合使用
# 在实际应用中(如 WebRTC)，通常采用 ICE (Interactive Connectivity Establishment) 框架结合 STUN 和 TURN：
# 首先尝试使用 STUN 建立直接连接
# 如果失败，则回退到 TURN 中继
# 整个过程对应用透明，自动选择最佳连接方式
# 这种组合方式既保证了在大多数情况下的高效直接连接，又在复杂网络环境下提供了可靠的通信保障。



# ICE (Interactive Connectivity Establishment) 是 WebRTC 中用于建立点对点连接的核心框架，
#       它通过系统化的方法解决 NAT 穿越和防火墙穿透问题，确保在各种网络环境下都能建立最优的媒体传输路径

# ICE 的核心组件
# Candidate (候选地址)
# ICE 收集多种可能的连接路径，称为"候选地址"，主要包括：
#         Host Candidate​​ (主机候选) 设备的本地 IP 地址和端口 优先级最高（如果可以直接连接）
# Server Reflexive Candidate​​ (服务器反射候选) 通过 STUN 服务器获取的 NAT 映射后的公网地址  优先级中等
# ​​Relay Candidate​​ (中继候选)  通过 TURN 服务器分配的中继地址   优先级最低（仅在其他方式失败时使用）


# ICE Agent 管理整个 ICE 过程的核心组件，负责
# 收集候选地址
# 排序候选地址对
# 执行连通性检查
# 确定最佳连接路径


# ICE 工作流程
# 1. 候选地址收集阶段
# 收集所有可能的网络接口地址（Host Candidate）
# 查询 STUN 服务器获取 Server Reflexive Candidate
# 如果配置了 TURN，获取 Relay Candidate
# 2. 候选地址交换
# 通过信令服务器交换双方的候选地址列表
# 使用 SDP (Session Description Protocol) 格式交换信息
# 3. 连通性检查 (Connectivity Checks)
# 按照优先级排序所有可能的候选地址对
# 双向发送 STUN 绑定请求进行连通性测试
# 遵循"冻结候选"机制控制检查顺序
# 4. 连接建立
# 第一个成功的检查对成为"有效候选对"
# 通知应用层连接已建立
# 开始媒体数据传输
# 5. 保活与维护
# 定期发送 STUN 请求保持 NAT 映射
# 监控连接质量，必要时触发重新协商


# 冻结候选
# 提名机制


# ICE 状态机
# ICE 连接过程有明确的阶段和状态：
# ​​新建 (New)​​：初始状态
# ​​收集候选 (Gathering)​​：正在收集候选地址
# ​​等待 (Waiting)​​：等待远程候选地址
# ​​检查中 (In-Progress)​​：执行连通性检查
# ​​完成 (Completed)​​：成功建立连接
# ​​失败 (Failed)​​：所有候选对检查失败
# ​​终止 (Terminated)​​：连接结束


# 常见 ICE 问题及解决方法：
# ​​长时间连接建立​​：检查 STUN/TURN 服务器可达性
# ​​只能使用 TURN​​：可能是对称 NAT 限制，检查防火墙设置
# ​​IPv6 问题​​：确保网络支持 IPv6 或明确禁用



# RTCRtpTransceiver :是 WebRTC 中管理媒体流发送和接收的核心组件，
#       在 aiortc 中实现了完整的 WebRTC 规范的 RTCRtpTransceiver 功能。
#       它代表一对关联的 RTCRtpSender 和 RTCRtpReceiver，用于双向媒体传输。

# 主要作用是：
# 管理  单个  媒体类型（音频或视频）的双向传输
# 控制媒体流的发送和接收方向
# 处理编解码器协商和媒体格式
# 管理传输的激活状态

# 可以动态设置传输方向（sendrecv, sendonly, recvonly, inactive）
# 参与 SDP 编解码器协商；管理首选编解码器顺序
# 将 MediaStreamTracks 与 RTP 传输关联
# 支持 BUNDLE 和 SDP 复用

from aiortc import RTCPeerConnection, MediaStreamTrack

pc = RTCPeerConnection()
# 添加传输器（通常通过 addTrack 自动创建）
transceiver = pc.addTransceiver("video")  # 或 "audio"
# 获取所有传输器
for transceiver in pc.getTransceivers():
    print(transceiver.mid, transceiver.kind, transceiver.direction)



# 主要属性
# mid (Media Identification)：唯一标识传输器的媒体部分标识符；在 SDP 中表示为 "a=mid" 行
# kind：媒体类型："audio" 或 "video"
# direction：当前方向："sendrecv", "sendonly", "recvonly" 或 "inactive"
# currentDirection：协商后的实际方向（可能不同于设置的方向）
# sender：关联的 RTCRtpSender 实例
# receiver：关联的 RTCRtpReceiver 实例
# stopped：布尔值，指示传输器是否已停止    

# 关键方法
# 设置传输方向：必须在 createOffer/createAnswer 前调用
transceiver.setDirection("sendonly")
# 停止传输器，释放相关资源
transceiver.stop()
# 设置首选 VP8 编解码器  （设置编解码器偏好顺序；影响本地描述中的编解码器顺序）
transceiver.setCodecPreferences([
    RTCRtpCodecParameters(name="VP8", clockRate=90000, payloadType=96)
])